package mesh;

import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL12.glDrawRangeElements;

import java.nio.FloatBuffer;
import java.nio.IntBuffer;

import loaders.OBJLoader;

import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.ARBVertexBufferObject;
import org.lwjgl.opengl.GLContext;

public class Mesh
{
	
	protected int totalVertices;
	protected int drawMode;
	protected int vertexBufferID;
	protected int colorBufferID;
	protected int textureCoordBufferID;
	protected int normalBufferID;
	protected int indexBufferID;
	
	public void loadFile( String path )
	{
		drawMode = GL_TRIANGLE_FAN;
		
		OBJLoader loader = new OBJLoader();
		loader.loadFile(path);
		
		float[] verts = loader.getVertices();
		int[] inds = loader.getFaces();
		float[] norms = loader.getNormals();
		totalVertices = verts.length;
		
		FloatBuffer vertices = BufferUtils.createFloatBuffer(verts.length);
	    IntBuffer indices = BufferUtils.createIntBuffer(inds.length);
	    FloatBuffer normals = BufferUtils.createFloatBuffer(norms.length);
	    
		for(int i = 0; i < verts.length; i++)
	    {
	        vertices.put(verts[i]);
	    }
		for(int i = 0; i < inds.length; i++)
	    {
			indices.put(inds[i]);
	    }
		for(int i = 0; i < norms.length; i++)
	    {
			normals.put(norms[i]);
	    }
		
		
		vertices.position(0);
		indices.position(0);
		
		vertexBufferID = createVBOID();
		bufferData(vertexBufferID, vertices);
		
		indexBufferID = createVBOID();
		bufferElementData(indexBufferID, indices);
		
//		normalBufferID = createVBOID();
//		bufferElementData(normalBufferID, normals);
	}
	
	public void render()
	{
		glFrontFace(GL_CCW);
		glEnable(GL_CULL_FACE);
		glCullFace(GL_BACK);
		
		if(vertexBufferID > 0 && indexBufferID > 0)
		{
			glEnableClientState(GL_VERTEX_ARRAY);
			ARBVertexBufferObject.glBindBufferARB(ARBVertexBufferObject.GL_ARRAY_BUFFER_ARB, vertexBufferID);
			glVertexPointer(3, GL_FLOAT, 0, 0);
			
	        if(colorBufferID > 0)
	        {
	            glEnableClientState(GL_COLOR_ARRAY);
	            ARBVertexBufferObject.glBindBufferARB(ARBVertexBufferObject.GL_ARRAY_BUFFER_ARB, colorBufferID);
	            glColorPointer(4, GL_FLOAT, 0, 0);
	        }
			
			if(textureCoordBufferID > 0)
	        {
	            glEnableClientState(GL_TEXTURE_COORD_ARRAY);
	            ARBVertexBufferObject.glBindBufferARB(ARBVertexBufferObject.GL_ARRAY_BUFFER_ARB, textureCoordBufferID);
	            glColorPointer(2, GL_FLOAT, 0, 0);
	        }

	        if(normalBufferID > 0)
	        {
	        	System.out.println("assdf");
//	            glEnableClientState(GL_NORMAL_ARRAY);
//	            ARBVertexBufferObject.glBindBufferARB(ARBVertexBufferObject.GL_ARRAY_BUFFER_ARB, normalBufferID);
//	            glNormalPointer(GL_FLOAT, 0, 0);
	        }
	        
	        ARBVertexBufferObject.glBindBufferARB(ARBVertexBufferObject.GL_ELEMENT_ARRAY_BUFFER_ARB, indexBufferID);
	        glDrawRangeElements(drawMode, 0, totalVertices, totalVertices, GL_UNSIGNED_INT, 0);
	        
	        glDisableClientState(GL_VERTEX_ARRAY);
	        glDisableClientState(GL_COLOR_ARRAY);
	        glDisableClientState(GL_TEXTURE_COORD_ARRAY);
	        glDisableClientState(GL_NORMAL_ARRAY);
		}
	}
	
	public static int createVBOID()
	{
		if (GLContext.getCapabilities().GL_ARB_vertex_buffer_object)
		{
			IntBuffer buffer = BufferUtils.createIntBuffer(1);
			ARBVertexBufferObject.glGenBuffersARB(buffer);
			
			return buffer.get(0);
		}
		
		return 0;
	}

	public static void bufferData(int id, FloatBuffer buffer)
	{
		if (GLContext.getCapabilities().GL_ARB_vertex_buffer_object)
		{
			ARBVertexBufferObject.glBindBufferARB(ARBVertexBufferObject.GL_ARRAY_BUFFER_ARB, id);
			ARBVertexBufferObject.glBufferDataARB(ARBVertexBufferObject.GL_ARRAY_BUFFER_ARB, buffer, ARBVertexBufferObject.GL_STATIC_DRAW_ARB);
		}
	}
	
	public static void bufferElementData(int id, IntBuffer buffer)
	{
		if (GLContext.getCapabilities().GL_ARB_vertex_buffer_object)
	    {
	        ARBVertexBufferObject.glBindBufferARB(ARBVertexBufferObject.GL_ELEMENT_ARRAY_BUFFER_ARB, id);
	        ARBVertexBufferObject.glBufferDataARB(ARBVertexBufferObject.GL_ELEMENT_ARRAY_BUFFER_ARB, buffer, ARBVertexBufferObject.GL_STATIC_DRAW_ARB);
	    }
	    
//	    System.out.println("here: ");
	    
	}

	@Override
	protected void finalize() throws Throwable
	{
	    if(vertexBufferID > 0) ARBVertexBufferObject.glDeleteBuffersARB(vertexBufferID);
	    if(colorBufferID > 0) ARBVertexBufferObject.glDeleteBuffersARB(colorBufferID);
	    if(textureCoordBufferID > 0) ARBVertexBufferObject.glDeleteBuffersARB(textureCoordBufferID);
	    if(indexBufferID > 0) ARBVertexBufferObject.glDeleteBuffersARB(indexBufferID);

	    super.finalize();
	}
	
	
//	private FloatBuffer mVerticesBuffer = null;
//
//	private ShortBuffer mIndicesBuffer = null;
//
//	private FloatBuffer mTextureBuffer;
//
//	private int mTextureId = -1;
//
////	private Bitmap mBitmap;
//
//	private boolean mShouldLoadTexture = false;
//
//	private int mNumOfIndices = -1;
//
//	private final float[] mRGBA = new float[] { 1.0f, 1.0f, 1.0f, 1.0f };
//
//	private FloatBuffer mColorBuffer = null;
//
//	public float x = 0;
//	public float y = 0;
//	public float z = 0;
//
//	public float rx = 0;
//	public float ry = 0;
//	public float rz = 0;
//
//	public void loadBitmap(Texture bitmap)
//	{
////		this.mBitmap = bitmap;
//		mShouldLoadTexture = true;
//	}
//	
////	public void loadFile(Context ctx, int resId)
////	{
////		OBJLoader loader = new OBJLoader();
////		loader.loadFile(ctx, resId);
////		
////		setVertices(loader.getVertices());
////		setIndices(loader.getFaces());
////		setTextureCoordinates( loader.getUVS());
////
////		System.out.println("stop!!!...");
////	}
//
////	public void draw(GL10 gl)
////	{
////		gl.glFrontFace(GL10.GL_CCW);
////
////		gl.glEnable(GL10.GL_CULL_FACE);
////
////		gl.glCullFace(GL10.GL_BACK);
////
////		gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
////
////		gl.glVertexPointer(3, GL10.GL_FLOAT, 0, mVerticesBuffer);
////
////		gl.glColor4f(mRGBA[0], mRGBA[1], mRGBA[2], mRGBA[3]);
////
////		if (mColorBuffer != null)
////		{
////			gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
////			gl.glColorPointer(4, GL10.GL_FLOAT, 0, mColorBuffer);
////		}
////
////		if (mShouldLoadTexture)
////		{
////			loadGLTexture(gl);
////			mShouldLoadTexture = false;
////		}
////		if (mTextureId != -1 && mTextureBuffer != null)
////		{
////			gl.glEnable(GL10.GL_TEXTURE_2D);
////
////			gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
////
////			gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, mTextureBuffer);
////			gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextureId);
////		}
////
////		gl.glTranslatef(x, y, z);
////		gl.glRotatef(rx, 1, 0, 0);
////		gl.glRotatef(ry, 0, 1, 0);
////		gl.glRotatef(rz, 0, 0, 1);
////
////		gl.glDrawElements(GL10.GL_TRIANGLES, mNumOfIndices, GL10.GL_UNSIGNED_SHORT, mIndicesBuffer);
////		
////		gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
////		
////		if (mTextureId != -1 && mTextureBuffer != null)
////		{
////			gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
////		}
////
////		gl.glDisable(GL10.GL_CULL_FACE);
////	}
//
//	protected void setVertices(float[] vertices)
//	{
//		ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4);
//		vbb.order(ByteOrder.nativeOrder());
//		mVerticesBuffer = vbb.asFloatBuffer();
//		mVerticesBuffer.put(vertices);
//		mVerticesBuffer.position(0);
//	}
//
//	protected void setIndices(short[] indices)
//	{
//		
//		ByteBuffer ibb = ByteBuffer.allocateDirect(indices.length * 2);
//		ibb.order(ByteOrder.nativeOrder());
//		mIndicesBuffer = ibb.asShortBuffer();
//		mIndicesBuffer.put(indices);
//		mIndicesBuffer.position(0);
//		mNumOfIndices = indices.length;
//	}
//
//	protected void setTextureCoordinates(float[] textureCoords)
//	{
//		ByteBuffer byteBuf = ByteBuffer.allocateDirect(textureCoords.length * 4);
//		byteBuf.order(ByteOrder.nativeOrder());
//		mTextureBuffer = byteBuf.asFloatBuffer();
//		mTextureBuffer.put(textureCoords);
//		mTextureBuffer.position(0);
//	}
//
//	protected void setColor(float red, float green, float blue, float alpha)
//	{
//		mRGBA[0] = red;
//		mRGBA[1] = green;
//		mRGBA[2] = blue;
//		mRGBA[3] = alpha;
//	}
//
//	protected void setColors(float[] colors)
//	{
//		ByteBuffer cbb = ByteBuffer.allocateDirect(colors.length * 4);
//		cbb.order(ByteOrder.nativeOrder());
//		mColorBuffer = cbb.asFloatBuffer();
//		mColorBuffer.put(colors);
//		mColorBuffer.position(0);
//	}
	
//	private void loadGLTexture(GL10 gl)
//	{
//		int[] textures = new int[1];
//		gl.glGenTextures(1, textures, 0);
//		mTextureId = textures[0];
//
//		gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextureId);
//
//		gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
//		gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
//
//		gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE);
//		
//		gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_REPEAT);
//
//		GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, mBitmap, 0);
//	}
}